import java.util.Map;

/*
 * @lc app=leetcode.cn id=523 lang=java
 *
 * [523] 连续的子数组和
 */

// @lc code=start
class Solution {
    /**
        在每个索引位置i, 计算当前和对k的mod值, 假设在索引x处, sum[0~x] = m*k + mod_x;
        在索引y处, sum[0~y] = n*k + mod_y; 如果mod_x == mod_y且y-x > 1说明sum[x~y]
        即为一个符合要求的连续子数组, 用map来保存每个mod值对应的索引, 一旦出现新的mod值出现
        在map中, 判断索引差是否大于1.
        注意特殊情况: 
        1) 当nums中有连续0, 无论k为何值都是正确的;
        2) 除情况1之外出现k为0都是错误的;
        3) k为负数也是可能的, 但是要将其变为对应正数来求mod.
        此外需要在map中初始化<0,-1>, 其原因在于解决到达某个i时sum恰好可以整除k的情况, 选择-1
        的原因是要求连续子数组长度大于等于2, 这样可以避免第一个数字为0的情况
        **/
    public boolean checkSubarraySum(int[] nums, int k) {
        if(nums.length<2) return false;

        for(int i = 0;i<nums.length-1;i++){
            if(nums[i]==0 && nums[i+1]==0) return true;//为k的0倍
        }
        if(k==0) return false;
        k = Math.abs(k);//可能有负数
        Map<Integer,Integer> mp = new HashMap<>();
        mp.put(0, -1);//极端情况，第一个数字为0，

        int sum = 0;
        for (int i = 0; i < nums.length; i++) {
            sum+=nums[i];
            int mod = sum %k;
            if(mp.containsKey(mod)){
                if(i-mp.get(mod)>1){//至少两者下标的要大于1，因为sum[0~y]-sum[0,x] = sum[x+1,y]; 即 y>x+1
                    return true;
                }
            }
            else{
                mp.put(mod, i);
            }
        }
        return false;
    }
}
// @lc code=end

